package huawei

import (
	"multitude-cloud-exporter/pkg/config"
	"multitude-cloud-exporter/pkg/config/base"
	"multitude-cloud-exporter/pkg/resource/common"
	"multitude-cloud-exporter/pkg/util"
	logger "multitude-cloud-exporter/pkg/util/log"
	"time"

	"multitude-cloud-exporter/pkg/cache"

	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/model"
	"github.com/prometheus/client_golang/prometheus"
)

type Resource struct {
	//TODO 需根据调用情况，调整
	*common.BaseResource
}

func NewResource(baseResource *common.BaseResource) (common.Resource, error) {
	return &Resource{
		baseResource,
	}, nil
}

func BatchUpdateMetrics(key, region_id, ctype string) {
	go batchUpdateMetrics(key, region_id, ctype)
}

func batchUpdateMetrics(key, region_id, ctype string) {
	for {
		select {
		case <-time.After(5 * time.Second):
			logger.Info("batch update : ", key)
			t := config.Huawei().Types[ctype]
			if nil == t {
				logger.Error("config now mush ", ctype)
				continue
			}
			rt, found := cache.Global.Get(key)
			if !found {
				logger.Error("cache not find ", key)
				continue
			}
			c, ok := rt.(cache.Cache)
			if !ok {
				return
			}
			for _, info := range t.MetricsInfo {
				resp, err := getValues(region_id, t.Namespace, info.MetricName, t.DimensionsName, c.Keys(), time.Now())
				if nil != err {
					logger.Error("get values err :", err)
					continue
				}
				if len(resp) == 0 {
					logger.Error("response in null.")
					continue
				}
				for _, res := range resp {
					if len(res.Datapoints) == 0 {
						continue
					}
					dimens := *res.Dimensions
					for _, dimen := range dimens {
						logger.Info("name : ", dimen.Name, " , value : ", dimen.Value, ", string : ", dimen.String())
						re, found := c.Get(dimen.Value)
						if !found {
							logger.Error("resource not in cache : ", dimen.Value)
							continue
						}

						r, ok := re.(*Resource)
						if !ok {
							logger.Error("resouce not cache")
							continue
						}
						if len(r.Metrics) == 0 || nil == r.Metrics {
							r.Metrics = make(map[string]common.Metric, len(t.MetricsInfo))
							for _, info := range t.MetricsInfo {
								r.Metrics[info.ReplacedMetricName] = common.NewMetric(
									info.ReplacedMetricName,
									prometheus.NewDesc(
										info.ReplacedMetricName,
										info.Desc,
										nil,
										util.MergeStringMap(
											r.Labels,
											info.CustomLabels,
										),
									),
								)
							}
						}
						r.updateMetrics(info, res)
					}

				}
			}
			logger.Info("batch update over : ", key)
		}
	}

}

func (r *Resource) updateMetrics(info *base.MetricInfo, resp model.BatchMetricData) {
	for _, metric := range r.Metrics {
		//配置文件
		if metric.GetMetricName() == info.ReplacedMetricName {
			metric.SetValueWithTs(
				*resp.Datapoints[0].Max,
				time.UnixMilli(resp.Datapoints[0].Timestamp),
			)
		}
	}
}

func (r *Resource) UpdateMetrics() {
	//TODO 调用云商API 更新Metric值
	//TODO 参数校验

	//TODO 可调整配置文件需要调整 ！！！！！
	//var typeConfig *huawei.Type
	//for _, t := range config.Huawei().Types {
	//	if t.Name == r.CloudType{
	//		typeConfig = t
	//	}
	//}
	//判断处理
	t := config.Huawei().Types[r.CloudType]
	if nil == t {
		logger.Error("config now mush ", r.Name)
		return
	}
	//TODO 空指针
	//
	r.Metrics = make(map[string]common.Metric, len(t.MetricsInfo))
	for _, info := range t.MetricsInfo {
		r.Metrics[info.ReplacedMetricName] = common.NewMetric(
			info.ReplacedMetricName,
			prometheus.NewDesc(
				info.ReplacedMetricName,
				info.Desc,
				nil,
				util.MergeStringMap(
					r.Labels,
					info.CustomLabels,
				),
			),
		)
	}

	for _, metric := range r.Metrics {
		//配置文件
		for _, info := range t.MetricsInfo {
			if metric.GetMetricName() == info.ReplacedMetricName {
				//TODO 调用云商接口SDK
				value, ts, err := getValue(r.Others["region_id"], t.Namespace, info.MetricName, t.DimensionsName, r.CloudID, time.Now())
				if err != nil {
					//TODO 错误处理
					logger.Infow("get value fail", "err", err.Error())

					//TODO 根据云商调用判断资源是否下线，打日志，或发飞书webhook通知。

					continue
				}
				metric.SetValueWithTs(value, time.UnixMilli(ts))
			}
		}
	}
}
